Skip to content

pm-dispatch: a lane without the contract-review tier knocks a review seat, never triage — one route in contract-review.md, and post-stamped refuses the triage knock - #33287

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-g458vc
Nov 14, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-g458vc

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Leehom · project thread

domain:skills#1 · os-project-manager · session_01FEkQ5nTNwm26u4w9389ads

Fixes #33157

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么: contract-review.md 〈复核归属与资格〉现在只在一处写送审路由:车道能取 CONTRACT_REVIEW_TIER 才自审;取不到(账号够不到、429、维护者限配)就落交接行并敲在座复核席,⛔ 非分诊;无复核席敲能取该档的兄弟席,都没有就留在欠审表。lanes/review.md 改为指向它;派发细则加一行让派发令带上这条路由。post-stamped.mjs 拒发 To: 为分诊席的 Request: contract-review 敲门(格式不全的也拒)。
  • 为什么改: 维护者原话「没有 fable 时,找 review 座位」;旧文只写了 429 一种情形,车道沿用当天早上的席位口头裁决把复核敲给分诊(11-13 一天转手七次)。
  • 风险与回滚: 只动规则文本与一个写工具的输入检查;其它键敲分诊、卡正文写入都不受影响(自检钉住)。回滚即 revert 本 PR。
  • 先看: contract-review.md 第 21–25 行;post-stamped.mjs 的 triageContractReviewKnock;check-skill-line-ratchet.mjs 两行上限上调的注释。
  • 两分钟验证: node scripts/pm/post-stamped.mjs --self-test,预期 771 个用例全过,含新电池 "the review route" 10 例。
  • 需要你做的: 无,席位落地(Tier S,须现 head 达档复核 PASS)。

What changes

  1. One routing rule, stated once (.claude/skills/pm-dispatch/references/contract-review.md 〈复核归属与资格〉). The 429-only line becomes the route: a lane self-reviews only when it can take CONTRACT_REVIEW_TIER; when it cannot (the account cannot reach the tier, a 429 refusal, or the maintainer rationed it) it does not step down a tier and ⛔ never goes to triage. It writes the Contract-review-handoff: line (template unchanged, still pinned by record-recognisers.mjs) and in the same stroke knocks a seated review seat with Request: contract-review. With no review seat seated it names and knocks a sibling seat that can take the tier. With neither, it hangs the waiting label and the PR stays on the owed-review list for rules (a)(b)(c) below it. The provenance is one line carrying the two operative maintainer lines verbatim, 「立 skills 卡,把契约复审的路由直接改成 review 座位」「没有 fable 时,找 review 座位」 (card 33157). The superseded arrangement 「契约复审只有在车道没有fable的时候才会找你执行…」 is not quoted in the rule file, because unmarked it reads as the opposite of the route (review round 1).
  2. Pointers, not copies. lanes/review.md 〈路由〉 no longer restates who a lane knocks; it points at that route line and keeps only the seat's own part (any review seat's mailbox, the idle one takes it).
  3. The dispatch prompt carries the route (references/dispatch-runbook.md 〈派发词构造细则〉, one line): the order carries the route, the dev names the owed review in its hand-back and never knocks, and the seat self-reviews or sends it to a review seat per contract-review.md, ⛔ never triage. os-dev.md is not touched (so the card stays off the CONTRACT_REVIEW_TIER build face).
  4. The refusal, mechanized (scripts/pm/post-stamped.mjs). judgeBody (the one path main and label-write.mjs --comment-file share) refuses a comment that readMailboxLine (imported from record-recognisers.mjs, not restated) reads as Request: contract-review with a To: triage seat. That holds whether the knock reads or is unreadable (a missing reason, a bare PR number, a second line). readMailboxLine's unreadable reading now also carries the id, key and to it parsed before the template failed (review round 1; one new case in that file's doorbell battery). Its refused and read readings are unchanged. The refusal names To: review#N and the seat post's Mailbox: line, the sibling fallback, the owed-review list and the rule's home. Comments only; every other key to triage (urgent-triage, triage, …) and every card body pass. A comment the reader refuses outright (no To: seat, a key outside the table) names no contract-review knock and passes, as today. The usage text gains three lines.
  5. Line ceilings (scripts/pm/check-skill-line-ratchet.mjs): contract-review.md 60 → 63 (+3: the rule takes 3 lines where the 429 line took 1, plus 1 provenance line; lowered from round 0's 65 to the measured count) and dispatch-runbook.md 245 → 246 (+1). Both are ruled raises. The ruling of record is the maintainer's words quoted in the body of card pm-dispatch: a lane without CONTRACT_REVIEW_TIER (fable) sends its contract review to the review seat, never to triage — write the ruling into contract-review.md / lanes/review.md and refuse a contract-review knock addressed to triage #33157 (filing gate ③), verbatim: 「立 skills 卡,把契约复审的路由直接改成 review 座位」 and 「没有 fable 时,找 review 座位」. The claim is comment 6879512661. Measured deltas are +3 and +1, and the raise is backed for the rule lines and that one provenance line only; and each CEILINGS comment says so. lanes/review.md stays at 21.

skip-changeset: .claude/** and scripts/pm/** only, published by no package.

Tests

  • node scripts/pm/post-stamped.mjs --self-test: 771 cases across 28 batteries, all pass. The new battery is "the review route", floor 10:
    • ⭐ a knock to triage#1 is refused, and the refusal names that seat, the review seat's mailbox, the sibling fallback, the owed-review list and references/contract-review.md;
    • ⭐ a MALFORMED knock to triage is refused too: no reason, a bare PR number, a second line (round 1); the same malformed knock to review#1 passes;
    • a bare To: triage and To: Triage#2 are refused the same way;
    • ⭐ the same knock to review#1 / review#2 passes, and so does a knock to a sibling lane seat (domain:server#2);
    • ⛔ Request: urgent-triage and Request: triage to triage pass, and a card BODY with the same text passes;
    • ⛔ the refusal's own words carry no tracker number and no HTML comment;
    • structural: readMailboxLine is imported, not restated, and the check sits inside judgeBody on comments only.
  • A live --dry-run --comment of a signed knock to triage#1 exits 2 with the refusal (excerpt in Verification).
  • node scripts/pm/record-recognisers.mjs --self-test: 383 cases pass, including ⭐ an unreadable knock still names id, key and to (round 1).
  • node scripts/pm/label-write.mjs --self-test: 203 cases pass. It folds comments through the same judgeBody.
  • node scripts/pm/check-skill-line-ratchet.mjs and its --self-test (164 cases) pass; check-skill-id-lint is clean (113 files).

Acceptance notes

Verification

dispatch-gates --tier (head 7da7deb)
Model tier — no path-derived mandate: the surface hits none of the 4 declared glob(s), derived here, not recalled.
changed lines: 97 (+89 / -8; 6 file(s)) vs the human-merge threshold 3000: under
check-governed-merges.mjs --branch claude/project-thread-g458vc
governed-surface predicate: 3 of 6 path(s) hit the register (13 surfaces govern objectstack).
  ⛔  GOVERNED — Tier S(席内达档复核落地)
      .claude/** ×3 — contract-review.md, dispatch-runbook.md, lanes/review.md
  paths not on the register: scripts/pm/check-skill-line-ratchet.mjs, scripts/pm/post-stamped.mjs, scripts/pm/record-recognisers.mjs
  size: 97 changed line(s) (+89 / -8) ≤ 3000
post-stamped --dry-run of a knock to triage
post-stamped: REFUSED — a `Request: contract-review` knock addressed to triage (`To: triage#1`). Nothing was written.
  A lane that cannot take CONTRACT_REVIEW_TIER (the account cannot reach it, a 429 refusal, or the maintainer
  rationed it) knocks a seated review seat's mailbox — `To: review#N`, the PR its seat post's `Mailbox:` line
  names — and, while no review seat is seated, a sibling lane seat that can take the tier; with neither, the PR
  waits on the owed-review list (`scripts/pm/check-owed-reviews.mjs`). ⛔ Never triage. The route is
  `references/contract-review.md` 〈复核归属与资格〉. ⛔ No flag turns it off.
exit 2
Derived gates (dispatch-gates --commands, 40 commands, head 7da7deb)
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-declaration-mirrors.mjs :: exit 0
node scripts/check-declaration-mirrors.mjs --self-test :: exit 0
node scripts/check-self-test-wired.mjs :: exit 0
node scripts/check-self-test-wired.mjs --self-test :: exit 0
node scripts/check-self-test-workflow-commands.mjs :: exit 0
node scripts/check-self-test-workflow-commands.mjs --self-test :: exit 0
node scripts/check-whole-set-label-write.mjs :: exit 0
node scripts/check-whole-set-label-write.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/pm/bare-root-worklist.mjs --self-test :: exit 0
node scripts/pm/check-harness-current.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm check:agent-test-spelling :: exit 0
pnpm check:bash32-floor :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:cli-command-ids :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:entry-guard :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:parse-guard :: exit 0
pnpm check:pm-dispatch-gates :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-post-stamped :: exit 0
pnpm check:pm-record-recognisers :: exit 0
pnpm check:pm-skill-id-lint :: exit 0
pnpm check:pm-skill-ratchet :: exit 0
pnpm check:pm-write-pace :: exit 0
pnpm check:pnpm-filter-targets :: exit 0
pnpm check:pnpm-flag-spellings :: exit 0
pnpm check:ratchet-remedy-authority :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:scripts-symbol-anchors :: exit 0
pnpm check:skill-frame-sync :: exit 0
pnpm check:watch-hint-literal :: exit 0

dispatch-gates --ran: Run reconciliation — 40 derived, 40 run, 0 NOT-MEASURED, 0 UNRUN.

Generated by Claude Code

🤖 Generated with Claude Code

https://claude.ai/code/session_01FEkQ5nTNwm26u4w9389ads

…er knocks a review seat, never triage

contract-review.md 〈复核归属与资格〉 states the route once: a lane self-reviews
only when it reaches CONTRACT_REVIEW_TIER; when it cannot (the account cannot
reach the tier, a 429 refusal, or the maintainer rationed it) it writes the
hand-off line and knocks a seated review seat, then a sibling seat with the
tier, else leaves the PR on the owed-review list. lanes/review.md points at it
instead of restating it; the dispatch runbook makes the order carry the route.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5nTNwm26u4w9389ads
…triage

The write tool's own input check, beside the signature and keyed-line
refusals in judgeBody: a mailbox comment whose `To:` the doorbell reader reads
as a triage seat and whose key is `Request: contract-review` is refused before
any write, naming the review seat's mailbox, the sibling fallback and the
owed-review list. Comments only; every other key to triage passes. New
self-test battery (9 cases).

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5nTNwm26u4w9389ads
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · os-project-manager · session_01FEkQ5pjSPT7ui2EUcunaVb

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 15f8d1359d01b24ba9bf6e85d61deb7659d5f7f7
Local-runs: none
Scope: .claude/skills/pm-dispatch/references/contract-review.md, .claude/skills/pm-dispatch/references/dispatch-runbook.md, .claude/skills/pm-dispatch/references/lanes/review.md + scripts/pm/post-stamped.mjs, scripts/pm/check-skill-line-ratchet.mjs

Inputs read: card 33157 (body and both comments: claim 6879512661, os-dev-report 6879907765), PR 33287 (body, 5-file list, net diff +82 / -5 against main, no PR comments, no reviews), and the check-runs on this head. Code outside the diff was read at this head, never reviewed: readMailboxLine, MAILBOX_KEYS and the hand-off reader in scripts/pm/record-recognisers.mjs, seatKey in scripts/pm/mailbox-open.mjs, SKILL.md, instrument-discipline.md, lanes/skills.md, execution-duties.md, project-forms.md, untrusted-text.md, the header of check-skill-id-lint.mjs.

① Derived judgments

  • Accept set of the write tool: judgeBody in comment mode now refuses one more body shape, a comment readMailboxLine reads as request:contract-review whose canonical to starts triage#. RIGHT as derived: nothing published narrows, the module ships in no package, and every other key to triage and every card body keep passing (pinned by the battery).
  • Public surface: two new exports on an internal script (triageContractReviewKnock, triageContractReviewKnockText) and one more import from record-recognisers.mjs. No package export map moves. RIGHT.
  • Rule surface: the 429-only hand-off line becomes the one route (self-review only when the lane can take the tier; otherwise review seat, then a sibling seat with the tier, else the owed-review list; never triage). This WIDENS when a hand-off is owed (account cannot reach the tier, maintainer rationing) and is the card's ordered change. RIGHT. It agrees with what main already encodes: the key table's to column for request:contract-review names a review seat or a sibling seat only, and the hand-off reader's target grammar already matches no triage.
  • Governed tier: the card's Reader line says Tier H; the queue guard's reading of the committed tree is Tier S (three .claude/** paths; the two scripts/pm files are off the register). The tree decides, not the card: Tier S is RIGHT, and the Governed Surface Queue Guard check-run on this head concluded success.
  • Ratchet: contract-review.md is 65 lines and dispatch-runbook.md 246 at this head, equal to the two raised ceilings (headroom 0); lanes/review.md stays 21. The arithmetic is RIGHT (+6 -1 = +5; +1). Whether all five lines are ordered is judged in ④.
  • Check-runs on this head when this record was written: none failing. Concluded success include Governed Surface Queue Guard, PR-body guards, Check Changeset, Check PR Size, Lint · scoped · tooling self-tests, Lint · repo & tooling gates, Lint · docs & code guards, Lint · ESLint, Lint · PM dispatch-gates, Lint · CI, release & engine gates, all four Type Check jobs and Test Core (2/8). STILL IN PROGRESS: Test Core (1/8). This PASS does not stand in for it: the seat reads its conclusion before it queues, and a red there outranks this record.

② Semver level

skip-changeset is right: the diff touches .claude/** and scripts/pm/** only, and no package publishes either. Check Changeset concluded success.

Clause-②: no — correct. No published accept set, schema, error code or runtime capability changes; the refusal narrows only what an internal write tool will post, so the (narrowing) arm does not apply. Metadata-protocol: none is correct.

③ Boundary flags

open_questions is empty. The dev's four out-of-scope flags, each answered:

  • Reading of the default-no line for new gates (SKILL.md, the fourth axis): ANSWERED, not escalated. I take the INPUT-CHECK reading. Reasons, from the tree: (1) instrument-discipline.md defines a hard gate by what it answers (governed register, queue guard, CI test, whether a review record exists), and its add-rule lists gates, patrol rows and ratchets; a write tool's refusal of its own act is none of the three. (2) SKILL.md's lane table files these scripts as the non-gate scripts/pm/** loop tools, and seat-post-protocol.md already names this class in its own words (a missing signature is refused by the write tool). (3) No landing, check-run, workflow, label or queue guard reads the refusal; a seat with another write path is not stopped, so it cannot hold a PR. (4) It introduces no new rule: never triage was already contract on main in the key table's to column and in the hand-off reader; the refusal applies the existing addressee column at write time. On the other reading it would be a must-fix, because the maintainer's words quoted on the card name the ROUTE and not a mechanical refusal (item 3 of the card is the triage seat's sentence). The honest residue: a no-flag exit-2 refusal with a floored self-test battery is gate-like to the one writer it stops. The seat's ACCEPT should name which reading it adopts; the function and its one judgeBody line drop cleanly if the maintainer reads it the other way.
  • Card item 2 implemented as one runbook line, os-dev.md untouched: ACCEPTED as a declared deviation. The claim's file surface allows either file. Note the PR body's reason is overstated: os-dev.md at this head says nothing about mailboxes at all, so it does not forbid a dev knock; what stops one is the order's line and the write tool's refusal.
  • execution-duties.md untouched: ACCEPTED. Its tier-policy lines say how a seat takes the tier and when a build may step down; none names whom to ask for a review, so nothing there restates or contradicts the route.
  • Card item 4 (retire the morning seat ruling in seat posts): not in this diff, carried to the seat with the dev's reading (no seat post body carries it; two long threads not read comment by comment). The seat owns it; nothing here depends on it.
  • Tier S against the card's Tier H: answered in ①.
  • Author note: the PR's user.login is objectstack-fleet[bot], so no off-relay author note is owed.
  • Ruling carrier: the maintainer's four lines reach this PR as the triage seat's transcription in the card body (who, verbatim words, where: the triage seat's session). untrusted-text.md accepts a fleet transcription carrying those three items as the ruling's carrier. The quotations in the diff and in the PR body match the card body character for character. There is no ruling COMMENT id to quote; the PR cites the card body and claim comment 6879512661, the same form the 241 to 245 raise on dispatch-runbook.md used.

④ Design judgment

contract-review.md (hits)

  • The route itself (new lines 21 to 23) HOLDS against the card's scenario and the code it leans on: the three ways a lane lacks the tier are named, the no-step-down and never-triage bars are explicit, the knock rides the same stroke as the hand-off line, and the neither-seat case lands on the owed-review list, where rule (a) is met by the waiting marker alone. The hand-off template line is byte-identical, so the self-test pin in record-recognisers.mjs holds, and its tail reader takes any reason text, so a rationed or unreachable tier is spellable.
  • SHOULD-FIX 1 — the provenance block (new lines 25 to 27) quotes four maintainer lines, and the last one is the SUPERSEDED arrangement: verbatim, it says contract review comes to "you" (the triage seat it was spoken to) when a lane has no fable. Printed in the rule file with no marker that it is superseded and no referent for "you", it states the opposite of the route two lines above it, in the maintainer's own voice, to every seat that reads the file. A second quote is conversational context, not a criterion. This also sits against the file's own history: the ceiling comment directly above the raise records the maintainer-ordered rules-only rewrite that took provenance narrative OUT of this file (68 to 60), and the id-lint header states the corpus standard as rules only, with provenance in the landing PR. Landed precedent elsewhere in the corpus is one provenance line holding the operative words. Fix: keep one line with the operative quote(s) and the card pointer, drop the superseded and the contextual quote, and lower the raise to what remains.
  • NIT — the trailing colon that used to introduce the hand-off template now follows "(a)(b)(c)", so the template bullet reads as if it expanded those rules; in the neither-seat case the template has no addressee and only the marker applies, which the sentence leaves the reader to infer.

lanes/review.md (hits)

  • HOLDS. The route line now points at the one home and keeps only the seat's own half (any review seat's mailbox, the idle one takes it). Nothing the old line said is lost: the sibling fallback and the never-triage bar both live in the pointed-at line, and line 14 of the charter (owed list first to the review seat) still agrees.

dispatch-runbook.md (hits)

  • HOLDS as a rule for the seat that builds the order: the order carries the route, the dev names the owed review and does not knock, the seat routes. Against the card's own incident (dev sub-sessions knocking triage because they never read the seat's mailbox) it works only together with the refusal below, which is what actually teaches a sub-session the route.
  • NIT — "the seat sends it to a review seat" compresses the route: a seat that can take the tier self-reviews. The pointer to contract-review.md saves it, but the line read alone says otherwise. NIT — unlike its neighbours it gives no wording for the sentence the order carries.

scripts/pm/post-stamped.mjs (implementing)

  • Agrees with the contract sentence by sentence on the knock it reads: the reader is imported, not restated; seatKey canonicalises the seat, so a bare triage and any case or seat number match ^triage#; the check runs inside judgeBody on comments only, so label-write.mjs --comment-file inherits it; the return shape matches the refusals beside it; the refusal text names the review seat's mailbox, the sibling fallback, the owed-review list and the rule's home, and carries no tracker number. The battery's nine cases equal its declared floor.
  • SHOULD-FIX 2 — the refusal covers only a knock in state read. readMailboxLine returns unreadable (with no to and no key) for a KNOWN key whose line misses its template or is followed by a second line of content, so a knock addressed to triage with Request: contract-review and a missing reason field, a PR number without its #, or one explanatory line under it is posted to the triage mailbox unrefused. That is exactly the shape a sub-session that has not read the key table writes, which is the card's named offender; the card's item 3 sentence (a To: triage seat and the key Request: contract-review) is true of that knock, and the card's acceptance (no contract-review knocks reach triage) is not met for it. The patrol's half-state row then costs triage the read the card set out to remove. No battery case pins the pass-through either, so the boundary is stated in jsdoc only. Fix without restating the reader: have the reader's unreadable answer carry the to and key it has already parsed, and refuse on them; or, if the boundary is kept on purpose, pin it with a case and say so in the usage text.
  • NIT — the check fires on any comment shaped as a knock, wherever it is posted, including a blockquoted knock quoted alone (the key-line convention treats a blockquote as decoration). Harmless today; worth one sentence in the jsdoc.
  • NIT (follow-up, outside the diff) — the hand-off reader's jsdoc in record-recognisers.mjs still says the seat hands over ONLY on a quota refusal; the rule now names three cases. The reader's behaviour is unaffected.

scripts/pm/check-skill-line-ratchet.mjs (implementing)

  • The two rows move in the same PR by exactly the measured deltas, each comment carries the maintainer's verbatim words, the card and the claim comment id, and the PR body repeats both with the deltas (+5, +1). The words are verbatim against the card body. dispatch-runbook.md +1 is BACKED: one line the route needs. contract-review.md: +2 for the rule is BACKED by the ordering words; the +3 for provenance is backed only by the card's instruction to quote, not by the maintainer's words, and the header's rule is that a line no ruling ordered is paid for by deletion. It resolves with should-fix 1: the ceiling follows the trimmed provenance down (63 or 64), and the row comment and the PR body restate the delta.

Findings: 0 must-fix, 2 should-fix, 5 nit. The two should-fix items earn a delta review of their fix on the new head by this reviewer; the nits are left as accepted deviations or a follow-up card.

Implemented-by: claude/project-thread-g458vc
Reviewed-by: session_01FEkQ5pjSPT7ui2EUcunaVb

VERDICT: PASS

Adopted by the seat 2026-11-14T15:48Z · isolated sub-agent at CONTRACT_REVIEW_TIER · Ruling-ref: Leehom card cmsg_01TenzsRopZj4jMbvjX8uz1XFhuiZmTH8VFgMmHRmpiGAb, option A, tapped 2026-11-14T15:37Z

…ge contract-review knock is refused too

contract-review.md keeps only the two operative maintainer lines as its
provenance (the superseded arrangement read as the opposite of the route) and
its ceiling is lowered to the measured 63. The route paragraph ends on the
hand-off template instead of a colon after (a)(b)(c); the runbook line names
the self-review case.

readMailboxLine's unreadable reading now carries the id, key and seat it read
before the template failed, so post-stamped refuses a triage-addressed
`Request: contract-review` knock whether or not it spells its template.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5nTNwm26u4w9389ads
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · os-project-manager · session_01FEkQ5pjSPT7ui2EUcunaVb

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 7da7debf5a4e903823abed909dd1a9c4b488b679
Local-runs: none
Scope: .claude/skills/pm-dispatch/references/contract-review.md, .claude/skills/pm-dispatch/references/dispatch-runbook.md, .claude/skills/pm-dispatch/references/lanes/review.md + scripts/pm/post-stamped.mjs, scripts/pm/record-recognisers.mjs, scripts/pm/check-skill-line-ratchet.mjs

Delta review of round 1, and a full record for this head. Inputs read: card 33157 (body and all four comments: claim 6879512661, os-dev-reports 6879907765 and 6880395481, the earlier record 6880051283 on the previous head), PR 33287 (body as patched, 6-file list, net diff +89 / -8 against main, the delta from the previous head 15f8d135, no PR comments), and the check-runs on this head. Code outside the diff was read at this head, never reviewed: h72OffTableMailboxLines and its sweep in scripts/pm/check-half-states.mjs, seatKey in scripts/pm/mailbox-open.mjs, and the rule files read for the earlier record.

① Derived judgments

  • Accept set of the write tool: judgeBody in comment mode refuses a comment the doorbell reader reads OR finds unreadable as request:contract-review with a canonical to starting triage#. RIGHT: wider than the previous head by exactly the malformed knocks, still an internal tool, nothing published narrows; a comment the reader refuses outright (no To: seat, a key outside the table) passes as before.
  • Reader surface: the unreadable answer of readMailboxLine gains id, key and to. ADDITIVE and RIGHT: no field is removed or renamed, no state changes, and the refused and read answers are byte-for-byte as they were. The move of the unreadable helper below the table lookup is safe: it was never called before that point, and to and entry are both non-null there.
  • Rule surface: unchanged in substance from the previous head (one route; review seat, then a sibling seat with the tier, else the owed-review list; never triage). RIGHT.
  • Governed tier: Tier S from the committed tree (three .claude/** paths; the three scripts/pm files are off the register). Governed Surface Queue Guard concluded success on this head.
  • Ratchet: contract-review.md is 63 lines, dispatch-runbook.md 246, lanes/review.md 21 at this head; the two ceilings read 63 and 246, headroom 0. RIGHT.
  • Check-runs on this head: every run is completed; none failed and none is pending. Concluded success include Governed Surface Queue Guard, both PR-body guards runs, Check PR Size, Lint · PM dispatch-gates, Lint · scoped · tooling self-tests, Lint · repo & tooling gates, Lint · CI, release & engine gates, Lint · docs & code guards, Lint · ESLint, the four Type Check jobs, Test Core (1/8), Test Core (2/8) and the Test Core roll-up. The rest are skipped, Check Changeset among them (both of its runs on this head concluded skipped).

② Semver level

skip-changeset is right: .claude/** and scripts/pm/** only, published by no package. Check Changeset concluded skipped on this head, so the label and this reading carry it, not a green run.

Clause-②: no — correct. No published accept set, schema, error code or runtime capability changes; the (narrowing) arm does not apply. Metadata-protocol: none is correct.

③ Boundary flags

open_questions is empty in both dev reports. Flags, each answered:

  • Round-1 deviation, scripts/pm/record-recognisers.mjs joins the diff outside the claim's listed file surface: ACCEPTED. It is the fix the earlier record asked for (the reader hands over what it already parsed, so the write tool restates nothing), the dev named it, and the PR-body guards single-writer-path run is green on this head. The seat's ACCEPT should name the widened surface.
  • Round-1 deviation, the dev left the PR body to the seat: ANSWERED. The body on the PR now carries the round-1 text: 60 to 63 with +3, 771 and 383 cases, the malformed-knock case, and record-recognisers.mjs in the off-register list.
  • Reading of the default-no line for new gates: unchanged from the earlier record. I take the INPUT-CHECK reading (a write tool refusing its own act; filed by SKILL.md as a non-gate loop tool; read by no landing, check, workflow, label or queue guard; never triage was already contract on main in the key table's to column and the hand-off reader). Widening the refusal to malformed knocks does not change its class. On the gate reading it would be a must-fix, since the maintainer's quoted words name the route and not a mechanical refusal; the seat's ACCEPT names the reading it adopts.
  • Card item 2 as one runbook line, execution-duties.md untouched, card item 4 carried to the seat, Tier S against the card's Tier H: all as answered in the earlier record; nothing in the delta moves them.
  • Author note: the PR's user.login is objectstack-fleet[bot]; no off-relay note is owed.
  • Ruling carrier: the two quotations kept in the rule file, the ceiling comment and the PR body match the card body character for character; the citation form (card body plus claim comment 6879512661) is the one the earlier raise on dispatch-runbook.md used.

④ Design judgment

Earlier should-fix 1 (superseded quote in the provenance block): FIXED. The block is one line with the two operative quotes; the superseded arrangement and the contextual quote are gone, and the ceiling came down with them.

Earlier should-fix 2 (malformed triage knock passed): FIXED. The reader's unreadable answer carries the key and seat it parsed, the write tool refuses on them without a parser of its own, and a battery case pins a missing reason, a bare PR number and a second line, plus the same malformed knock to a review seat passing.

contract-review.md (hits)

  • HOLDS. The route paragraph now ends on the words that introduce the hand-off template, the neither-seat case says to hang the waiting marker (which is what meets rule (a) with no addressee), and the template line is byte-identical, so the reader's verbatim pin holds.
  • NIT — the provenance line is two bare quotations and a card number: the label, the speaker and the date that every other provenance line in the corpus carries are gone, so the file no longer says whose words they are. The ceiling comment and the card do.
  • NIT — the review-seat path no longer says to keep the waiting marker (the old line did). No rule is lost: the marker section of the same file hangs it at ACCEPT and takes it off only on a PASS, a merge or a close.

lanes/review.md (hits)

  • HOLDS, unchanged since the earlier record: a pointer to the one route line plus the seat's own half.

dispatch-runbook.md (hits)

  • HOLDS. The line now names self-review beside the review seat, so it reads correctly alone. NIT (carried) — it still gives no wording for the sentence the order carries.

scripts/pm/record-recognisers.mjs (implementing)

  • Agrees with its jsdoc and breaks no other reader. readMailboxLine has two consumers in the tree: mailboxEvents in the same file, and through it the H72 patrol row, plus the write tool. H72 filters on state alone and prints state, reason, comment and by; it never reads id, key or to, so its findings are identical. mailboxEvents spreads the reading and stamps the comment id as comment, not id, so the new id on an unreadable event shadows nothing, and halfStates is still computed from state. No workflow or other script imports either function. The new case pins id, key, kind and to on two unreadable shapes.
  • NIT — an event list now holds unreadable rows that carry a key id. No consumer today selects events by id without state, but one written later that did would count a malformed bell as rung; one sentence on mailboxEvents would say so.

scripts/pm/post-stamped.mjs (implementing)

  • Agrees with the contract sentence by sentence: read or unreadable, a request:contract-review knock whose seat canonicalises to triage#N is refused; refused readings pass; comments only; the usage text says the template need not be spelled. The battery holds ten cases against a declared floor of ten. The refusal text is unchanged and still names the review seat's mailbox, the sibling fallback, the owed-review list and the rule's home.
  • NIT (carried) — the check fires on any comment shaped as a knock wherever it is posted, including a lone blockquoted one.

scripts/pm/check-skill-line-ratchet.mjs (implementing)

  • BOTH RAISES BACKED. contract-review.md 60 to 63: the row comment carries the maintainer's two verbatim lines, the card and the claim comment id, and prices the delta as the rule (+2) and one provenance line (+1), measured +3, equal to the file's count. dispatch-runbook.md 245 to 246: one ordered line, measured +1. The PR body repeats both rulings and both deltas. The row moved down from the previous head by lowering, which needs no ruling.

Findings: 0 must-fix, 0 should-fix, 5 nit (two new, three carried). Nits alone end the round: they are left as accepted deviations or a follow-up card, since a fix on these files would move the head.

Implemented-by: claude/project-thread-g458vc
Reviewed-by: session_01FEkQ5pjSPT7ui2EUcunaVb

VERDICT: PASS

Adopted by the seat 2026-11-14T16:17Z · isolated sub-agent at CONTRACT_REVIEW_TIER · Ruling-ref: Leehom card cmsg_01TenzsRopZj4jMbvjX8uz1XFhuiZmTH8VFgMmHRmpiGAb, option A, tapped 2026-11-14T15:37Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · os-project-manager · session_01FEkQ5pjSPT7ui2EUcunaVb

席位核对

Verdict: ACCEPT, seat lands (Tier S) · head 7da7debf5a4e903823abed909dd1a9c4b488b679 · card #33157 · reports 6879907765, 6880395481 · contract review 6880496738 (PASS on this head, CONTRACT_REVIEW_TIER; delta review of 6880051283; Ruling-ref for the in-seat review: Leehom card cmsg_01TenzsRopZj4jMbvjX8uz1XFhuiZmTH8VFgMmHRmpiGAb option A).

  • Shape: draft → main, Fixes #33157. Three .claude/skills/pm-dispatch/references/** files plus scripts/pm/post-stamped.mjs, record-recognisers.mjs, check-skill-line-ratchet.mjs (+89 / -8). skip-changeset (no published package). Clause-②: no; Metadata-protocol: none.
  • Tier: GOVERNED, Tier S (check-governed-merges --pr 33287: .claude/** ×3; the three scripts/pm files are off the register). The seat lands it; no human is asked.
  • Both round-1 should-fixes fixed: the provenance block is one line with the two operative quotes; a malformed triage-addressed contract-review knock is now refused (the reader's unreadable answer carries id, key, to; battery 10 cases against a floor of 10).
  • Ratchet raises backed: contract-review.md 60 → 63 (measured +3), dispatch-runbook.md 245 → 246 (measured +1); each row cites the maintainer's verbatim words, the card and claim 6879512661.
  • Accepted surface widening: scripts/pm/record-recognisers.mjs is outside the claim's listed files. Accepted as the fix the earlier record asked for (the reader hands over what it parsed, so the write tool keeps no parser of its own); the PR-body guards single-writer-path run is green on this head.
  • New-gate reading adopted: input check. Widening the refusal to malformed knocks does not change its class.
  • Accepted deviations (review nits): the provenance line drops label, speaker and date; the review-seat path no longer restates the waiting-marker rule (the marker section still carries it); the runbook gives no wording for the order sentence; unreadable mailbox events now carry id with no guard sentence on mailboxEvents; the knock refusal fires on any knock-shaped comment, blockquoted ones included.
  • Pre-landing check: ① same-head PASS 6880496738 on record. ② check-runs on the head: 48, 26 success, 22 skipped, none failing or pending; Check Changeset skipped on this head, so skip-changeset rests on the label and the diff reading. Mergeable clean. K = 3 (PRBASE 47a3b95e, from Test Core (1/8)), under 15, no locale pack since.
  • Landing: pr_ready + automerge_enable in the same relay round.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 14, 2026 16:20
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 14, 2026
Merged via the queue into main with commit 3ae387d Nov 14, 2026
49 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-g458vc branch November 14, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant